package com.sigmatrix.h5.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONObject;
import com.sigmatrix.h5.dao.ProductDao;
import com.sigmatrix.h5.dto.PackStandardData;
import com.sigmatrix.h5.dto.ProductData;
import com.sigmatrix.h5.entity.Product;
import com.sigmatrix.h5.enums.ResponseEnum;
import com.sigmatrix.h5.exception.DaoException;
import com.sigmatrix.h5.exception.ServiceException;
import com.sigmatrix.h5.request.Request;
import com.sigmatrix.h5.response.Response;
import com.sigmatrix.h5.service.PackStandardService;
import com.sigmatrix.h5.service.ProductService;
import com.sigmatrix.h5.utils.Cons;
import com.sigmatrix.h5.utils.Utils;
import com.sigmatrix.h5.web.vo.PackStandardVo;
import com.sigmatrix.h5.web.vo.ProductVo;
import com.sigmatrix.sc.jdbc.common.service.ServiceImpl;
/**
 * 
 *@ClassName: ProductServiceImpl
 *@Description: 
 *@author MH
 *@date 2017年9月26日 下午5:57:41
 */
@Service
public class ProductServiceImpl extends ServiceImpl<Product,Integer> implements ProductService{
	
	/**logger record*/
	private static final Logger LOGGER = LoggerFactory.getLogger(ProductServiceImpl.class);
	
	@Autowired
	private ProductDao productDao;
	
	/**包装规格信息*/
	@Autowired
	private transient PackStandardService packStandardService;
	
	@Override
	public Product findByBasicModuleId(Integer basicModuleId) {
		Product product = new Product();
		product.setBasicModuleId(basicModuleId);
		return productDao.selectOne(product);
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: getCountHaveSpecifiedLevelCount
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#getCountHaveSpecifiedLevelCount(com.sigmatrix.sc.handheld.inter.dto.ProductData, int, int)
	 *@author youjun
	 *@date 2017年8月13日 下午3:42:21
	 */
	@Override
	public int getCountHaveSpecifiedLevelCount(final ProductData product, final int currentLevel,
			final int specifiedLevel) throws ServiceException {

		if(product==null
				|| CollectionUtils.isEmpty(product.getPackStandard())
				|| currentLevel < 2
				|| specifiedLevel < 1
				|| currentLevel < specifiedLevel) {
			throw new ServiceException("参数有误");
		}
		if(currentLevel==specifiedLevel) {
			return 1;
		}
		final List<PackStandardData> packStandardLevelList = product.getPackStandard();
		// key为包装级别,value为对应的下级数量
		final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for(final PackStandardData pack:packStandardLevelList) {
			map.put(pack.getLevel().intValue(), pack.getSubNum());
		}
		// codeLevel(eg：3)必须大于specifiedLevel(eg：2)
		int specifiedLevelCount = 1;
		for(int i=currentLevel;i>specifiedLevel;i--){
			specifiedLevelCount = specifiedLevelCount*map.get(i);
		}
		return specifiedLevelCount;
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: findById
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#findById(java.lang.Integer)
	 *@author youjun
	 *@date 2017年6月25日 下午3:23:55
	 */
	@Override
	public ProductData findById(final Integer id, final String enterpriseCode) throws ServiceException {
		
		if(id==null) {
			throw new ServiceException("请指定主键");
		}
		
		final ProductData data = new ProductData();
		try {
			final Product product = productDao.findById(id, enterpriseCode);
			if(product!=null) {
				data.setProductId(product.getId());
				data.setProductName(product.getName());
				data.setProductCode(product.getCode());
				data.setNormsValue(product.getNormsValue());
				data.setNormsUnit(product.getNormsUnit());
				data.setProductUnit(product.getPackLevel());
				final PackStandardVo packStandardVo = new PackStandardVo();
				packStandardVo.setProductId(data.getProductId());
				packStandardVo.setEnterpriseCode(enterpriseCode);
				final List<PackStandardData> packStandardList = packStandardService.findPartColumnListByCondition(packStandardVo);
				data.setPackStandard(packStandardList);
				// 填充包装单位和单品单位
				fillPackAndSingleUnitEtcInfo(data, packStandardList);
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return data;
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: findById
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#findById(java.lang.Integer, boolean, java.lang.String)
	 *@author youjun
	 *@date 2017年8月27日 下午10:40:03
	 */
	@Override
	public ProductData findById(final Integer id, final boolean isSelectPack, final String enterpriseCode) throws ServiceException {
		
		if(id==null) {
			throw new ServiceException("请指定主键");
		}
		if(isSelectPack) {
			return findById(id, enterpriseCode);
		}
		final ProductData data = new ProductData();
		try {
			final Product product = productDao.findById(id, enterpriseCode);
			if(product!=null) {
				data.setProductId(product.getId());
				data.setProductName(product.getName());
				data.setProductCode(product.getCode());
				data.setNormsValue(product.getNormsValue());
				data.setNormsUnit(product.getNormsUnit());
				data.setProductUnit(product.getPackLevel());
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return data;
	}
	
	/**
	 *@Title: fillPackAndSingleUnitEtcInfo
	 *@Description: 填充包装规格相关信息,包装单位、单品单位、包装map、包装级别list等
	 *@return void
	 *@author youjun
	 *@date 2017年8月7日 下午3:49:38
	 *@param data
	 *@param packStandardList
	 */
	private void fillPackAndSingleUnitEtcInfo(final ProductData productData, final List<PackStandardData> packStandardList) {

		if(productData!=null && !CollectionUtils.isEmpty(packStandardList)) {
			// 所有的包装规格level集合
			final List<Integer> packStandardLevelList = new ArrayList<Integer>();
			// 所有的包装规格map,key为包装规格level,value为对应的包装规格name
			final Map<Integer, String> packStandardMap = new HashMap<Integer, String>();
			final Map<Integer, Integer> packStandardSubNumMap = new HashMap<Integer, Integer>();
			for(final PackStandardData data:packStandardList) {
				if(data.getLevel()!=null) {
					packStandardLevelList.add(data.getLevel().intValue());
					packStandardMap.put(data.getLevel().intValue(), data.getName());
					packStandardSubNumMap.put(data.getLevel().intValue(), data.getSubNum());
					if(data.getLevel().intValue()==1) {
						productData.setSingleUnit(data.getName());
					}else if(productData.getProductUnit()!=null 
							&&data.getLevel().intValue()==productData.getProductUnit().intValue()){
						productData.setPackUnit(data.getName());
					}
				}
			}
			Collections.sort(packStandardLevelList);
			productData.setPackStandardLevelList(packStandardLevelList);
			productData.setBigLevel(packStandardLevelList.get(packStandardLevelList.size()-1));
			productData.setPackStandardMap(packStandardMap);
			productData.setPackStandardSubNumMap(packStandardSubNumMap);
		}
	}

	/**
	 * (non-Javadoc)
	 *@Title: findPartColumnListByCondition
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#findPartColumnListByCondition(com.sigmatrix.sc.handheld.inter.web.vo.ProductVo)
	 *@author youjun
	 *@date 2017年6月26日 下午2:41:43
	 */
	@Override
	public List<ProductData> findPartColumnListByCondition(final ProductVo productVo) throws ServiceException {
		
		validateBasicParamsThrow(productVo, false, false);
		final Product product = new Product();
		BeanUtils.copyProperties(productVo, product);
		try {
			final List<ProductData> dataList = productDao.findPartColumnListByCondition(product, productVo.getEnterpriseCode());
			// 填充产品的包装规格等信息
			fillPackStandardInfo(dataList, productVo.getEnterpriseCode());
			return dataList;
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	
	/**
	 *@Title: validateBasicParamsThrow
	 *@Description: 验证基础参数,验证不通过抛出异常
	 *@return void
	 *@author youjun
	 *@date 2017年8月4日 下午5:31:21
	 *@param request
	 *@param isValidTerminalId
	 *@param isValidUserId
	 *@throws ServiceException
	 */
	protected void validateBasicParamsThrow(final Request request, final boolean isValidTerminalId, 
			final boolean isValidUserId) throws ServiceException {
		
		if(request==null) {
			throw new ServiceException("参数不能为空");
		}
		if(StringUtils.isBlank(request.getEnterpriseCode())) {
			throw new ServiceException("企业code不能为空");
		}
		if(isValidUserId && request.getUserId()==null) {
			throw new ServiceException("终端用户ID不能为空");
		}
	}
	

	/**
	 *@Title: fillPackStandardInfo
	 *@Description: 填充产品的包装规格信息
	 *@return void
	 *@author youjun
	 *@date 2017年6月26日 下午2:19:47
	 *@param dataList
	 * @throws ServiceException 
	 */
	private void fillPackStandardInfo(final List<ProductData> dataList, final String eseCode) throws ServiceException {
		if(!CollectionUtils.isEmpty(dataList)) {
			List<PackStandardData> packStandardList = null;
			PackStandardVo packStandardVo = null;
			for(final ProductData data:dataList) {
				packStandardVo = new PackStandardVo();
				packStandardVo.setProductId(data.getProductId());
				packStandardVo.setEnterpriseCode(eseCode);
				packStandardList = packStandardService.findPartColumnListByCondition(packStandardVo);
				data.setPackStandard(packStandardList);
				// 填充包装单位和单品单位
				fillPackAndSingleUnitEtcInfo(data, packStandardList);
			}
		}
	}

	/**
	 * (non-Javadoc)
	 *@Title: findListByCondition
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#findListByCondition(com.sigmatrix.sc.handheld.inter.web.vo.ProductVo)
	 *@author youjun
	 *@date 2017年6月25日 下午3:23:51
	 */
	@Override
	public List<ProductData> findListByCondition(final ProductVo productVo) throws ServiceException {

		final List<ProductData> dataList = new ArrayList<ProductData>();
		try {
			final Product product = new Product();
			if(productVo!=null) {
				BeanUtils.copyProperties(productVo, product);
			}
			final List<Product> list = productDao.findListByCondition(product, productVo.getEnterpriseCode());
			if(!CollectionUtils.isEmpty(list)) {
				ProductData data = null;
				for(final Product item:list) {
					data = new ProductData();
					BeanUtils.copyProperties(item, data);
					dataList.add(data);
				}
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return dataList;
	}
	
	/**
	 *@Title: getAllProductMap
	 *@Description: 获得所有产品的map
	 *@return Map<Integer,ProductData>
	 *@author youjun
	 *@date 2017年6月25日 下午2:18:06
	 *@return
	 * @throws ServiceException 
	 */
	@Override
	public Map<Integer, ProductData> getAllProductMap(final String enterpriseCode) throws ServiceException {
		
		final Map<Integer, ProductData> productMap = new HashMap<Integer, ProductData>();
		final List<ProductData> productList = getAllProductList(enterpriseCode);
		if(!CollectionUtils.isEmpty(productList)) {
			for(final ProductData data:productList) {
				productMap.put(data.getProductId(), data);
			}
		}
		return productMap;
	}

	/**
	 *@Title: getAllProductList
	 *@Description: 获得所有产品的集合
	 *@return List<ProductData>
	 *@author youjun
	 *@date 2017年6月25日 下午2:16:02
	 *@return
	 * @throws ServiceException 
	 */
	@Override
	public List<ProductData> getAllProductList(final String enterpriseCode) throws ServiceException {
		
		LOGGER.info("当前企业:{},基础数据中的产品为空,将从数据库中查询产品信息", enterpriseCode);
		final ProductVo productVo = new ProductVo();
		productVo.setEnterpriseCode(enterpriseCode);
		final List<ProductData> productList = findPartColumnListByCondition(productVo);
		LOGGER.info("当前企业:{},查询的所有产品列表为:{}", enterpriseCode, JSONObject.toJSONString(productList));
		return productList;
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: getProductFromMap
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#getProductFromMap(java.util.Map, java.lang.Integer)
	 *@author youjun
	 *@date 2017年6月25日 下午3:26:09
	 */
	@Override
	public ProductData getProductFromMap(final Map<Integer, ProductData> productMap, final Integer productId, final String enterpriseCode) throws ServiceException {
		
		if(productMap==null) {
			throw new ServiceException("map不能为null");
		}
		if(productId==null || productId.intValue()==Cons.NULL_PRIMARY_KEY_VALUE) {
			return null;
		}
		if(productMap.containsKey(productId)) {
			return productMap.get(productId);
		}
		final ProductData data = findById(productId, enterpriseCode);
		productMap.put(productId, data); // 放入map中
		return data;
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: getProductFromCache
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#getProductFromCache(java.lang.Integer)
	 *@author youjun
	 *@date 2017年7月3日 下午9:34:29
	 */
	@Override
	public ProductData getProductFromCache(final Integer productId, final String enterpriseCode) throws ServiceException {
		if(productId!=null) {
			return findById(productId, enterpriseCode);
		}
		return null;
	}

	/**(non-Javadoc)
	 * @throws ServiceException 
	 *@Title: syncProductList
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#syncProductList(com.sigmatrix.sc.handheld.inter.web.vo.ProductVo)
	 *@author youjun
	 *@date 2017年6月26日 下午7:22:04
	 */
	@Override
	public Response syncProductList(final ProductVo productVo) throws ServiceException {

		try{
			// 参数验证
			final Response validateResponse = validateParams(productVo);
			LOGGER.info("参数验证结果:{}", JSONObject.toJSONString(validateResponse));
			if(validateResponse.getCode().intValue()!=Cons.RESPONSE_CODE_SUCCESS) {
				return validateResponse;
			}
			final List<ProductData> productList = findPartColumnListByCondition(productVo);
			LOGGER.info("同步产品列表接口查询的产品列表为:", JSONObject.toJSONString(productList));
			LOGGER.info("替换基础数据中的产品列表和产品map为同步接口的查询结果");
			return new Response(ResponseEnum.SUCCESS, productList);
		}catch(Exception e) {
			LOGGER.error("syncProductList fail", e);
			throw new ServiceException(e);
		}
	}

	/**
	 *@Title: validateParams
	 *@Description: TODO()
	 *@return Response
	 *@author youjun
	 *@date 2017年6月27日 上午11:24:07
	 *@param productVo
	 *@return
	 */
	private Response validateParams(final ProductVo productVo) {
		return validateBasicParams(productVo);
	}
	
	/**
	 *@Title: validateBasicParams
	 *@Description: 验证公共参数,<b>企业code、用户ID不能为空,非该逻辑请调用其他</b>
	 *@return Response
	 *@author youjun
	 *@date 2017年6月27日 上午11:10:14
	 *@param request
	 */
	protected Response validateBasicParams(final Request request) {
		if(Utils.isEmpty(request)) {
			return new Response(ResponseEnum.PARAM_NULL);
		}
		if(Utils.isEmpty(request.getEnterpriseCode())){
			return new Response(Cons.RESPONSE_CODE_PARAM_INVALID, "企业code不能为空");
		}
		if(Utils.isEmpty(request.getUserId())){
			return new Response(Cons.RESPONSE_CODE_PARAM_INVALID, "用户ID不能为空");
		}
		return new Response(ResponseEnum.SUCCESS);
	}
	
	/**
	 * (non-Javadoc)
	 *@Title: getCodeHaveSpecifiedLevelCount
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.ProductService#getCodeHaveSpecifiedLevelCount(com.sigmatrix.sc.handheld.inter.dto.ProductData, int, int)
	 *@author youjun
	 *@date 2017年8月14日 下午10:14:45
	 */
	@Override
	public int getCodeHaveSpecifiedLevelCount(final ProductData product, final int codeLevel,
			final int specifiedLevel) throws ServiceException {

		if(product==null
				|| CollectionUtils.isEmpty(product.getPackStandard())
				|| codeLevel < 2
				|| specifiedLevel < 1
				|| codeLevel < specifiedLevel) {
			throw new ServiceException("参数有误");
		}
		if(codeLevel==specifiedLevel) {
			return 1;
		}
		final List<PackStandardData> packStandardLevelList = product.getPackStandard();
		// key为包装级别,value为对应的下级数量
		final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for(final PackStandardData pack:packStandardLevelList) {
			map.put(pack.getLevel().intValue(), pack.getSubNum());
		}
		// codeLevel(eg：3)必须大于specifiedLevel(eg：2)
		int specifiedLevelCount = 1;
		for(int i=codeLevel;i>specifiedLevel;i--){
			specifiedLevelCount = specifiedLevelCount*map.get(i);
		}
		return specifiedLevelCount;
	}
	
	
	/**(non-Javadoc)
	 * @throws ServiceException 
	 *@Title: syncProductList
	 *@Description: 
	 *@see com.sigmatrix.h5.service.ProductService#syncProductList(com.sigmatrix.sc.distribution.app.inter.web.vo.Request)
	 *@author youjun
	 *@date 2017年6月26日 下午7:22:04
	 */
	@Override
	public Response syncProductList(final Request request) throws ServiceException {
		try{
			final List<ProductData> dataList = productDao.findAllForSysn(request.getEnterpriseCode());
			// 填充产品的包装规格等信息
			fillPackStandardInfo(dataList, request.getEnterpriseCode());
			return new Response(ResponseEnum.SUCCESS,dataList);
		}catch(Exception e) {
			LOGGER.error("syncProductList fail", e);
			throw new ServiceException(e);
		}
	}

}
